package org.zfes.snowier.cloud.zbss.pmp.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.zfes.snowier.core.data.ComboboVo;
import org.zfes.snowier.core.data.DataSet;
import org.zfes.snowier.core.data.TreeVo;
import org.zfes.snowier.core.data.ZTreeVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.zfes.snowier.core.util.ZBeanUtil;
import org.zfes.snowier.core.util.ZDateUtil;
import org.zfes.snowier.core.util.ZObjectUtil;

import com.google.common.collect.Lists;

import org.zfes.snowier.core.util.ZAlert;
import org.zfes.snowier.core.util.ZAssert;
import org.zfes.snowier.common.dao.params.ParamMap;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpCloudMemberService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpProjectService;
import org.zfes.snowier.cloud.zbss.pmp.service.IPmpRequiresService;
import org.zfes.snowier.cloud.zbss.pmp.dao.PmpRequiresMapper;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpModuleCreateDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpRequiresCreateDto;
import org.zfes.snowier.cloud.zbss.pmp.dto.PmpRequiresUpdateDto;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpCloudMember;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpProject;
import org.zfes.snowier.cloud.zbss.pmp.model.PmpRequires;

import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class PmpRequiresServiceImpl implements IPmpRequiresService{
 	@Autowired
	private PmpRequiresMapper pmpRequiresMapper;
	
 	@Autowired
	private IPmpCloudMemberService pmpCloudMemberService;
 	@Autowired
	private IPmpProjectService pmpProjectService;

	
 	@Transactional(rollbackFor=Exception.class)
 	@Override
	public Long  createRoot(Long projectId,String name) {
 		ZAssert.notNull(projectId, "参数错误");
 		ZAssert.hasText(name, "名称不能为空");
 		PmpRequires root = pmpRequiresMapper.selectRootByProjectId(projectId);
 		ZAssert.isNull(root, "根节点已经存在");
 		
 		PmpProject pmpProject=pmpProjectService.loadPmpProjectById(projectId).orElseThrow(()->ZAlert.newSLE("未查询到项目信息"));
		ZAssert.equals(pmpProject.getStatus(), Byte.valueOf("1"), "项目已经删除或者结束");
		
 		
 		PmpRequires pmpRequires=new PmpRequires();
 		pmpRequires.setProjectId(projectId);
 		pmpRequires.setProjectVersionId(pmpProject.getVersionId());
 		pmpRequires.setProjectVersionName(pmpProject.getVersionName());
 		pmpRequires.setTreeCode(""+pmpProject.getId()+"_");
 		pmpRequires.setName(name);
 		pmpRequires.setReType(Byte.valueOf("0"));
 		pmpRequires.setParentId(Long.valueOf("-1"));
 		pmpRequires.setCreatetime(ZDateUtil.newDate());
 		pmpRequires.setUpdatetime(ZDateUtil.newDate());
 		pmpRequiresMapper.insertSelective(pmpRequires);
 		return pmpRequires.getId();
 	}
 	
 	@Transactional(rollbackFor=Exception.class)
 	@Override
	public Long createModule(PmpModuleCreateDto moduleCreateDto) {
 		ZBeanUtil.validateBean(moduleCreateDto);
 		
 		PmpRequires parent=pmpRequiresMapper.selectByPrimaryKey(moduleCreateDto.getParentId());
 		ZAssert.notNull(parent, "未找到父节点数据");
 		ZAssert.equals(parent.getStatus(), Byte.valueOf("1"), "父节点已经被删除");
 		
 		PmpRequires pmpRequires=new PmpRequires();
 		ZBeanUtil.copy(moduleCreateDto, pmpRequires, true);
 		//#0根模块，1需求，2模块#
 		pmpRequires.setReType(Byte.valueOf("2"));
 		
 		
 		pmpRequires.setProjectId(parent.getProjectId());
 		pmpRequires.setProjectVersionId(parent.getProjectVersionId());
 		pmpRequires.setProjectVersionName(parent.getProjectVersionName());
 		
 		PmpCloudMember chargeUser=pmpCloudMemberService.loadPmpCloudMemberById(moduleCreateDto.getChargeUserId()).orElseThrow(()->ZAlert.newSLE("未查询到该用户"));
		ZAssert.equals(chargeUser.getStatus(), Byte.valueOf("1"), "负责人用户状态错误");
		pmpRequires.setChargeUserName(chargeUser.getUserName());
		pmpRequires.setCreatetime(ZDateUtil.newDate());
 		pmpRequires.setUpdatetime(ZDateUtil.newDate());
		
		pmpRequiresMapper.insertSelective(pmpRequires);
 		Long id= pmpRequires.getId();
 		
 		
 		pmpRequiresMapper.updateTreeCode(id,parent.getTreeCode()+id+"_");
 		
 		return id;
 	}
 	
 	
 	@Transactional(rollbackFor=Exception.class)
 	@Override
	public void createPmpRequires(PmpRequiresCreateDto requiresDto) {
 		ZBeanUtil.validateBean(requiresDto);
 		
 		PmpRequires pmpRequires=new PmpRequires();
 		
 		PmpRequires parent=pmpRequiresMapper.selectByPrimaryKey(requiresDto.getParentId());
 		ZAssert.notNull(parent, "未找到父节点数据");
 		ZAssert.equals(parent.getStatus(), Byte.valueOf("1"), "父节点已经被删除");
 		ZAssert.notEquals(parent.getReType(), Byte.valueOf("1"), "父节点不能是需求");
 		
 		ZBeanUtil.copy(requiresDto, pmpRequires, true);
 		
		PmpProject pmpProject=pmpProjectService.loadPmpProjectById(requiresDto.getProjectId()).orElseThrow(()->ZAlert.newSLE("未查询到项目信息"));
		ZAssert.equals(pmpProject.getStatus(), Byte.valueOf("1"), "项目已经删除或者结束");
		pmpRequires.setProjectVersionId(pmpProject.getVersionId()).setProjectVersionName(pmpProject.getVersionName());
		
		PmpCloudMember chargeUser=pmpCloudMemberService.loadPmpCloudMemberById(requiresDto.getChargeUserId()).orElseThrow(()->ZAlert.newSLE("未查询到该用户"));
		ZAssert.equals(chargeUser.getStatus(), Byte.valueOf("1"), "负责人用户状态错误");
		pmpRequires.setChargeUserName(chargeUser.getUserName());

		ZBeanUtil.setCreateInfo(pmpRequires);
		pmpRequires.setReType(Byte.valueOf("1"));
		ZBeanUtil.validateBean(pmpRequires);
		
		pmpRequires.setCreatetime(ZDateUtil.newDate()).setUpdatetime(ZDateUtil.newDate());
		
		pmpRequiresMapper.insertSelective(pmpRequires);
		
		Long id= pmpRequires.getId();
 		pmpRequiresMapper.updateTreeCode(id,parent.getTreeCode()+id+"_");
 		
		
	}
 	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updatePmpRequires(PmpRequiresUpdateDto requiresUpdateDto) {
 		ZBeanUtil.validateBean(requiresUpdateDto);
 		
		ZAssert.notNull(requiresUpdateDto.getId(), "参数错误");
		
		PmpRequires pmpRequires=loadPmpRequiresById(requiresUpdateDto.getId()).orElseThrow(()->ZAlert.newSLE("未查询到数据"));
		ZAssert.equals(pmpRequires.getStatus(), Byte.valueOf("1"), "该需求已被删除");
		
		ZBeanUtil.copy(requiresUpdateDto, pmpRequires, true);
		
		PmpCloudMember chargeUser=pmpCloudMemberService.loadPmpCloudMemberById(requiresUpdateDto.getChargeUserId()).orElseThrow(()->ZAlert.newSLE("未查询到该用户"));
		ZAssert.equals(chargeUser.getStatus(), Byte.valueOf("1"), "负责人用户状态错误");
		pmpRequires.setChargeUserName(chargeUser.getUserName());
		
		ZBeanUtil.setUpdatedInfo(pmpRequires);
		ZBeanUtil.validateBean(pmpRequires);
		pmpRequires.setUpdatetime(ZDateUtil.newDate());
		pmpRequiresMapper.updateByPrimaryKeySelective(pmpRequires);
	}
 	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updateModuleName(Long id,String newname) {
		ZAssert.hasText(newname, "请输入新名字");
		ZAssert.notNull(id, "参数错误");
		
		PmpRequires pmpRequires=loadPmpRequiresById(id).orElseThrow(()->ZAlert.newSLE("未查询到数据"));
		ZAssert.equals(pmpRequires.getStatus(), Byte.valueOf("1"), "该需求模块已被删除");
		ZAssert.notEquals(pmpRequires.getReType(), Byte.valueOf("1"), "非模块");
		
		pmpRequiresMapper.updateModuleName( id, newname);
	}
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void updateOrderNum(Long id,Integer orderNum) {
		ZAssert.bigOrEqThanZero(orderNum, "请输入正确的顺序值", "请输入正确的顺序值");
		ZAssert.notNull(id, "参数错误");
		
		PmpRequires pmpRequires=loadPmpRequiresById(id).orElseThrow(()->ZAlert.newSLE("未查询到数据"));
		ZAssert.equals(pmpRequires.getStatus(), Byte.valueOf("1"), "该需求已被删除");
		
		pmpRequiresMapper.updateOrderNum( id, orderNum);
	}
 
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<PmpRequires> loadPmpRequiresById(Long id) {
		if(id!=null){
			return Optional.ofNullable(pmpRequiresMapper.selectByPrimaryKey(id));
		}
		return Optional.empty();
	}
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void setPmpRequiresStatus(Long id, Byte status) {
		ZAssert.notNull(id, "请选择要操作的数据");
		ZAssert.notNull(status, "状态参数错误");
		if(!Stream.of(new Byte[] {-1,1}).anyMatch(val->val.equals(status))) {
			ZAlert.serviceLogicalError("状态参数错误");
		}
		pmpRequiresMapper.updateStatus( id,  status) ;
		
		if(Byte.valueOf("-1").equals(status)) {
			PmpRequires requires=pmpRequiresMapper.selectByPrimaryKey(id);
			if(requires!=null) {
				pmpRequiresMapper.updateStatusByParentTreeCode(""+requires.getTreeCode()+"%"+"",status);
			}
			
		}
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<ZTreeVo> loadRequiresZTreeVo(Long projectId) {
	
		List<PmpRequires> requireList=pmpRequiresMapper.selectByProjectId(projectId,Byte.valueOf("1"));
		if(ZObjectUtil.isEmpty(requireList)) {
			return Lists.newArrayList();
		}
		return requireList.stream()
				.map(req->ZTreeVo.newEmpty().setId(req.getId()).setPid(req.getParentId())
						.setName(
						Byte.valueOf("1").equals(req.getReType())?"[需求]"+req.getName():(Byte.valueOf("2").equals(req.getReType())?"[模块]"+req.getName():req.getName())
						).setNodeType(""+req.getReType()))
				.collect(Collectors.toList());
		
	
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public Optional<TreeVo>  loadRequiresTreeVo(Long projectId) {
	
		List<PmpRequires> requireList=pmpRequiresMapper.selectByProjectId(projectId,Byte.valueOf("1"));
		if(ZObjectUtil.isEmpty(requireList)) {
			return Optional.empty();
		}
		
		PmpRequires root=requireList.stream().filter(val->val.getReType().equals(Byte.valueOf("0"))).findFirst().get();
		Lists.newArrayList();
		TreeVo rootVo=TreeVo.newEmpty();
		
		traverse( rootVo,root, requireList);
		
		return Optional.ofNullable(rootVo);
	}
	
	private void traverse(TreeVo rootVo,PmpRequires require,List<PmpRequires> requireList) {
		
		rootVo.setId(require.getId()).setText(require.getName()).setParentId(require.getParentId()).setChildList(new ArrayList<TreeVo>());
		
		List<PmpRequires> children= requireList.stream().filter(val->val.getParentId().equals(require.getId())).collect(Collectors.toList());
		
		if(ZObjectUtil.isNotEmpty(children)) {
			
			children.forEach(val->{

				TreeVo childVo=TreeVo.newEmpty().setId(val.getId()).setText(val.getName()).setParentId(val.getParentId());
				rootVo.addChild(childVo);
				traverse(childVo,val, requireList);
				
			});
		}
		
	}
	
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public DataSet loadPmpRequiresDataSet(Map<String, Object> params) {
		ParamMap pm=ParamMap.filterParam(params);
		pm.getObj("parentId").ifPresent(v->pm.updateParam("parentId", "%"+v+"%"));
		pm.getObj("treeCode").ifPresent(v->pm.updateParam("treeCode", "%"+v+"%"));
		pm.getObj("name").ifPresent(v->pm.updateParam("name", "%"+v+"%"));
		DataSet ds=DataSet.newDS2(pmpRequiresMapper.selectListCount(pm), pmpRequiresMapper.selectMapListPage(pm));
		return ds;
	}

	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<ComboboVo> loadComboboVo(Long projectId, boolean firstEmpty) {
		List<ComboboVo> voList=pmpRequiresMapper.selectComboboVo(projectId,null);
		if(firstEmpty) {
			voList.add(0, ComboboVo.newEmptyFirst());
		}
		return voList;
	}
	
}